package com.axialproject.health.exchange.google;

import com.google.gdata.client.health.H9Service;
import com.google.gdata.client.http.AuthSubUtil;
import com.google.gdata.data.Entry;
import com.google.gdata.data.PlainTextConstruct;
import com.google.gdata.util.XmlBlob;
import com.axialproject.health.exchange.EMF;
import com.axialproject.health.exchange.PatientManager;
import com.axialproject.health.exchange.Router;
import com.axialproject.health.exchange.Record;
import com.axialproject.health.exchange.entity.Patient;
import com.google.gdata.client.health.HealthService;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityManager;

public class RouterImpl implements Router {

    private static final Logger log = Logger.getLogger(RouterImpl.class.getName());

    @Override
    public void sendRecord(Patient patient, Record record) {

        log.info ("The patient passed into the Google router: " + patient.getId());
        log.info ("The record passed into Google router is " + record.getDescription());

        PrivateKey privateKey = null;
        try {
            privateKey = AuthSubUtil.getPrivateKeyFromKeystore("WEB-INF/classes/ringful.jks", "ringful", "health-exchange", "ringful");
        } catch (Exception e) {
            log.log(Level.SEVERE, e.getMessage(), e);
        }

        // The patient is from the source, we need to find the gpatient
        Patient gpatient = null;
        EntityManager em = EMF.get().createEntityManager();
        try {
            List <Patient> patients = PatientManager.getLinkedPatients(em, patient.getId());
            for (Patient p : patients) {
                if ("google".equals(p.getAppName()) && p.getToken() != null) {
                    boolean validToken = false;
                    try {
                        Map<String, String> tokenInfo = AuthSubUtil.getTokenInfo(p.getToken(), privateKey);
                        // Map<String, String> tokenInfo = AuthSubUtil.getTokenInfo(p.getToken(), null);
                        if (tokenInfo != null) {
                            validToken = true;
                        }
                    } catch (Exception te) {
                        log.log(Level.SEVERE, te.getMessage(), te);
                    }

                    if (validToken) {
                        gpatient = p;
                        break;
                    }
                }
            }

            if (gpatient == null) {
                log.info ("The google user does not exist or the google token is no longer valid");
                return;
            }
        } catch (Exception e) {
            log.log(Level.SEVERE, e.getMessage(), e);
        } finally {
            em.close ();
        }



        try {
            Entry newNotice = null;
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");

            String ccrDoc = "<ContinuityOfCareRecord xmlns='urn:astm-org:CCR'>" +
                "<CCRDocumentObjectID>" + UUID.randomUUID().toString() + "</CCRDocumentObjectID>" +
                "<Language><Text>English</Text></Language>" +
                "<Version>V1.0</Version>" +
                "<DateTime><ExactDateTime>" + formatter.format(new Date ()) + "</ExactDateTime></DateTime>" +
                "<Patient><ActorID>" + gpatient.getEmail() + "</ActorID></Patient>" +
                "<Body>";

            // if ("allergy".equals(record.getType())) {
            if (record.getAllergyAllergens() != null && record.getAllergyAllergens().size() != 0) {
                ccrDoc += "<Alerts>";
                String ccrTemplate = readFileAsString("/allergy_ccr.xml");
                for (int i = 0; i < record.getAllergyAllergens().size(); i++) {
                    String ccr = ccrTemplate.replaceAll("\\#\\{start_date\\}", formatter.format(record.getStart()))
                                            .replaceAll("\\#\\{stop_date\\}", formatter.format(record.getStop()))
                                            .replaceAll("\\#\\{severity\\}", record.getAllergySeverities().get(i))
                                            .replaceAll("\\#\\{allergen\\}", record.getAllergyAllergens().get(i))
                                            .replaceAll("\\#\\{doctor_name\\}", record.getDoctorName())
                                            .replaceAll("\\#\\{doctor_title\\}", "Treating clinician");
                    ccrDoc += ccr;
                }
                ccrDoc += "</Alerts>";
            }

            // if ("testresult".equals(record.getType())) {
            if (record.getTestNames() != null && record.getTestNames().size() != 0) {
                ccrDoc += "<Results>";
                String ccrTemplate = readFileAsString("/testresult_ccr.xml");
                for (int i = 0; i < record.getTestNames().size(); i++) {
                    String ccr = ccrTemplate.replaceAll("\\#\\{start_date\\}", formatter.format(record.getStart()))
                                            .replaceAll("\\#\\{stop_date\\}", formatter.format(record.getStop()))
                                            .replaceAll("\\#\\{test_name\\}", record.getTestNames().get(i))
                                            .replaceAll("\\#\\{test_result\\}", record.getTestResults().get(i))
                                            .replaceAll("\\#\\{test_result_unit\\}", record.getTestResultUnits().get(i))
                                            .replaceAll("\\#\\{test_result_normal_range\\}", record.getTestResultNormalRanges().get(i))
                                            .replaceAll("\\#\\{doctor_name\\}", record.getDoctorName())
                                            .replaceAll("\\#\\{doctor_title\\}", "Ordering clinician");
                    ccrDoc += ccr;
                }
                ccrDoc += "</Results>";
            }

            if (record.getMedications() != null && record.getMedications().size() != 0) {
                ccrDoc += "<Medications>";
                String ccrTemplate = readFileAsString("/medication_ccr.xml");
                for (int i = 0; i < record.getMedications().size(); i++) {
                    String ccr = ccrTemplate.replaceAll("\\#\\{start_date\\}", formatter.format(record.getStart()))
                                            .replaceAll("\\#\\{stop_date\\}", formatter.format(record.getStop()))
                                            .replaceAll("\\#\\{medication\\}", record.getMedications().get(i))
                                            .replaceAll("\\#\\{medication_dose\\}", record.getMedicationDoses().get(i))
                                            .replaceAll("\\#\\{medication_dose_unit\\}", record.getMedicationDoseUnits().get(i))
                                            .replaceAll("\\#\\{doctor_name\\}", record.getDoctorName())
                                            .replaceAll("\\#\\{doctor_title\\}", "Prescribing clinician");
                    ccrDoc += ccr;
                }
                ccrDoc += "</Medications>";
            }

            if (record.getConditions() != null && record.getConditions().size() != 0) {
                ccrDoc += "<Problems>";
                String ccrTemplate = readFileAsString("/condition_ccr.xml");
                for (int i = 0; i < record.getConditions().size(); i++) {
                    String ccr = ccrTemplate.replaceAll("\\#\\{start_date\\}", formatter.format(record.getStart()))
                                            .replaceAll("\\#\\{stop_date\\}", formatter.format(record.getStop()))
                                            .replaceAll("\\#\\{condition\\}", record.getConditions().get(i))
                                            .replaceAll("\\#\\{doctor_name\\}", record.getDoctorName())
                                            .replaceAll("\\#\\{doctor_title\\}", "Treating clinician");
                    ccrDoc += ccr;
                }
                ccrDoc += "</Problems>";
            }
            
            ccrDoc += "</Body></ContinuityOfCareRecord>";
            log.info ("CCR content is " + ccrDoc);

            newNotice = new Entry();
            newNotice.setTitle(new PlainTextConstruct(record.getTitle()));
            newNotice.setContent(new PlainTextConstruct(record.getDescription()));
            if (ccrDoc != null) {
                XmlBlob ccrElement = new XmlBlob();
                ccrElement.setBlob(ccrDoc);
                newNotice.setXmlBlob(ccrElement);
            }

            if (newNotice != null) {
                HealthService service = new HealthService("Ringful-Axial-1.0");
                // H9Service service = new H9Service("Ringful-H9Sample-1.0");
                service.setAuthSubToken(gpatient.getToken(), privateKey);
                Entry createdNotice = service.insert(new URL("https://www.google.com/health/feeds/register/default"), newNotice);
                // Entry createdNotice = service.insert(new URL("https://www.google.com/h9/feeds/register/default"), newNotice);
            }

        } catch (Exception e) {
            log.log(Level.SEVERE, e.getMessage(), e);
        }
    }

    private String readFileAsString(String fileOnClasspath) throws IOException{
        InputStream is = this.getClass().getResourceAsStream(fileOnClasspath);
        StringBuilder fileData = new StringBuilder(1000);
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        char[] buf = new char[1024];
        int numRead=0;
        while((numRead=reader.read(buf)) != -1){
            fileData.append(buf, 0, numRead);
        }
        reader.close();
        return fileData.toString();
    }

}
